﻿using System;
using System.Diagnostics;
using System.IO;

namespace Rocuna.Log
{
    /// <summary>
    /// Logger class 
    /// </summary>
    public class Logger : IDisposable
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="Logger"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="debuggerOutput">if set to <c>true</c> [debugger output].</param>
        public Logger(string name, bool debuggerOutput)
        {
            _loggerLevel = LogDetailsLevel.Normal;
            _debugOut = debuggerOutput;
            Name = name;
        }

        #endregion

        #region Properties

        protected LogDetailsLevel _loggerLevel;

        /// <summary>
        /// Sets the logger level.
        /// </summary>
        /// <value>
        /// The logger level.
        /// </value>
        public LogDetailsLevel LoggerLevel { set { _loggerLevel = value; } }

        protected bool _debugOut;

        /// <summary>
        /// Sets a value indicating whether [debug output].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [debug output]; otherwise, <c>false</c>.
        /// </value>
        public bool DebugOutput { set { _debugOut = value; } }

        /// <summary>
        /// Gets or sets the logger name.
        /// </summary>
        /// <value>
        /// The logger name.
        /// </value>
        public string Name { get; set; }

        /// <summary>
        /// Raising when message logged.
        /// </summary>
        public event EventHandler<MessageLoggedEventArgs> MessageLogged;

        #endregion

        #region Raising methods

        protected void RaiseMessageLogged(MessageLoggedEventArgs eventArgs)
        {
            if (MessageLogged != null)
                MessageLogged(this, eventArgs);
        }

        #endregion

        #region logging logic

        /// <summary>
        /// Logs the message.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="level">The level.</param>
        /// <param name="maskDebug">if set to <c>true</c> [mask debug].</param>
        public void LogMessage(string msg, LogLevel level, bool maskDebug)
        {
            if (string.IsNullOrEmpty(msg))
                throw new ArgumentException("Logged message can't be null");
            if (!((int)level < (int)_loggerLevel))
            {
                RaiseMessageLogged(new MessageLoggedEventArgs() { Msg = msg, Level = level, MaskDebug = maskDebug });
                if (_debugOut && !maskDebug)
                {
                    switch (level)
                    {
                        case LogLevel.Debug:
                            Trace.TraceInformation(msg);
                            break;
                        case LogLevel.Error:
                            Trace.TraceError(msg);
                            break;
                        case LogLevel.Warning:
                            Trace.TraceWarning(msg);
                            break;
                    }
                }

            }
        }

        #endregion

        #region Adding trace Listeners

        /// <summary>
        /// Adds the trace listener.
        /// </summary>
        /// <param name="listener">The listener.</param>
        public void AddTraceListener(TraceListener listener)
        {
            Trace.Listeners.Add(listener);
        }

        /// <summary>
        /// Removes the trace listener.
        /// </summary>
        /// <param name="name">The name.</param>
        public void RemoveTraceListener(string name)
        {
            Trace.Listeners.Remove(name);
        }

        #endregion

        #region Implementation of IDisposable

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {

        }

        #endregion
    }
}
